package store.lunangangster.engine.impl.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import store.lunangangster.engine.Agenda;
import store.lunangangster.engine.impl.Context;
import store.lunangangster.engine.impl.agenda.NodeFlowEngineAgenda;
import store.lunangangster.engine.impl.agenda.Operation;
import store.lunangangster.engine.impl.cmd.Command;

/**
 * 最终的Command执行器。与其他的拦截器不同，该拦截器不会继续再调用{@link #next}的{@link CommandInterceptor#execute(Command)}方法。
 * 可以理解为该对象是整个拦截器链上的末端。
 *
 * <p>该执行器会执行所有存在于{@link Agenda}中的所有操作。单独传入的Command也会被放入到Agenda中被执行
 *
 * @author cwk
 * @version 1.0
 */
public class CommandInvoker implements CommandInterceptor {

  private static final Logger log = LoggerFactory.getLogger(CommandInvoker.class);

  @Override
  public <T> T execute(Command<T> command) {
    CommandContext commandContext = Context.getCommandContext();
    NodeFlowEngineAgenda agenda = commandContext.getAgenda();
    // 添加到Agenda中
    agenda.addOperation(() -> {
      log.debug("执行命令: " + command);
      commandContext.setResult(command.execute(commandContext));
    }, false);
    log.debug("添加命令: {}", command);

    // 循环执行Agenda中注册的操作
    executeOperations(agenda);

    // 执行完成之后，判断是否还有涉及到的Execution
    // 如果有，则将其保持静默
    // if (commandContext.hasInvolvedExecution()) {
    // }
    log.debug("命令完成: {}", command);
    return (T) commandContext.getResult();
  }

  protected void executeOperations(Agenda agenda) {
    while (agenda.hasNext()) {
      Runnable task = agenda.getNextOperation();
      if (task instanceof Operation) {
        Operation operation = (Operation) task;
        log.debug("执行操作: " + operation.getClass());
        operation.run();
      } else {
        task.run();
      }
    }
  }

  /**
   * 由于该类作为拦截器链上的末端，该方法返回null
   * @return  null
   */
  @Override
  public CommandInterceptor next() {
    return null;
  }

  @Override
  public void setNext(CommandInterceptor nextInterceptor) {
    // do nothing
  }

  @Override
  public boolean hasNext() {
    return false;
  }
}
